// 教师接口

package api

import (
	"api/common"
	"api/common/logger"
	"api/common/orm"
	"api/common/web"
	"api/models"
	"encoding/base64"
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"os"
	"time"
)

// @TagName 教师接口
// @Controller TeacherController
type TeacherController struct{}

// @Title 提交用户报名信息(教师代报)
// @Route /teacher/submit --> Submit
// @Param {"data":{}}
// @Method post
func (this *TeacherController) Submit(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.ExemptTokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	data := inputJson["data"]
	if data == nil {
		web.ServeJSON(w, web.JsonMsg{false, "报名信息不能为空", 1})
		return
	}

	modelMap := data.(map[string]interface{})
	user := &models.Info{}
	web.JsonToStruct(modelMap, user)

	if user.Phone == "" {
		web.ServeJSON(w, web.JsonMsg{false, "手机号码不能为空", 1})
		return
	}
	if user.IdCardNum == "" {
		web.ServeJSON(w, web.JsonMsg{false, "身份证号码不能为空", 1})
		return
	}

	// 只有应届生才需要填写准考证号和报名号
	isYingJie := user.Situation == 1 || user.Situation == 3
	if isYingJie {
		if user.ExamCardNum == "" {
			web.ServeJSON(w, web.JsonMsg{false, "准考证号不能为空", 1})
			return
		}
		if user.Signup == "" {
			web.ServeJSON(w, web.JsonMsg{false, "报名号不能为空", 1})
			return
		}
	}

	// 验证"报名信息"的有效性, 防止重复报名
	type Counts struct {
		Phone       uint32
		Idcardnum   uint32
		Examcardnum uint32
		Signup      uint32
	}
	counts := &Counts{}
	conn := orm.NewOrm()
	var err error
	sql := "select" +
		" (select count(1) from student_info where phone=?) phone," +
		" (select count(1) from student_info where id_card_num=?) idcardnum"
	if isYingJie {
		sql += " (select count(1) from student_info where exam_card_num=?) examcardnum," +
			" (select count(1) from student_info where signup=?) signup"
		err = conn.Raw(sql, user.Phone, user.IdCardNum, user.ExamCardNum, user.Signup).QueryRow(counts)
	} else {
		err = conn.Raw(sql, user.Phone, user.IdCardNum).QueryRow(counts)
	}
	if err != nil {
		logger.Info("验证报名信息的有效性时发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "验证报名信息的有效性时发生错误" + err.Error(), 1})
		return
	}

	if counts.Phone > 0 {
		web.ServeJSON(w, web.JsonMsg{false, "手机号码已经存在，请勿重复报名。", 1})
		return
	}
	if counts.Idcardnum > 0 {
		web.ServeJSON(w, web.JsonMsg{false, "身份证号码已经存在，请勿重复报名。", 1})
		return
	}

	if isYingJie {
		if counts.Examcardnum > 0 {
			web.ServeJSON(w, web.JsonMsg{false, "准考证号已经存在，请勿重复报名。", 1})
			return
		}
		if counts.Signup > 0 {
			web.ServeJSON(w, web.JsonMsg{false, "报名号已经存在，请勿重复报名。", 1})
			return
		}
	}

	user.Id = 0
	user.Status = 1 // 更新用户状态为: 已报名待审核
	_ = conn.Begin()
	_, err = conn.Insert(user)
	if err != nil {
		_ = conn.Rollback()
		logger.Error("新增记录发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "新增记录发生错误" + err.Error(), 1})
		return
	}

	rec := &models.OperateRecord{
		StudentId: user.Id,
		Status:    1, // 已报名待审核
		Remark:    "教师代报 " + user.Recommend,
	}
	_, err = conn.Insert(rec)
	if err != nil {
		_ = conn.Rollback()
		logger.Error("操作记录入库发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "操作记录入库发生错误" + err.Error(), 1})
		return
	}
	_ = conn.Commit()

	result := map[string]interface{}{}
	result["status"] = 0
	result["success"] = true
	result["msg"] = "提交报名信息成功"
	result["user"] = user
	web.ServeJSON(w, result)
}

// @Title 上传用户相关图片(教师代报)
// @Route /teacher/upload --> Upload
// @Param {"b64":"base64Code", "b64sm":"base64Code", "imgType":"jpg", "fieldName":"picture"}
// @Method post
func (this *TeacherController) Upload(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.ExemptTokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	b64 := inputJson["b64"]
	b64sm := inputJson["b64sm"]
	imgType := inputJson["imgType"]
	fieldName := inputJson["fieldName"]

	if b64 == nil || b64 == "" {
		web.ServeJSON(w, web.JsonMsg{false, "图片数据不能为空", 1})
		return
	}
	if b64sm == nil || b64sm == "" {
		web.ServeJSON(w, web.JsonMsg{false, "缩略图数据不能为空", 1})
		return
	}
	if imgType == nil {
		web.ServeJSON(w, web.JsonMsg{false, "图片扩展名不能为空", 1})
		return
	}
	if fieldName == nil {
		web.ServeJSON(w, web.JsonMsg{false, "图片字段名不能为空", 1})
		return
	}

	imgStr, err := base64.StdEncoding.DecodeString(b64.(string))
	if err != nil {
		logger.Error("图片数据不正确", err)
		web.ServeJSON(w, web.JsonMsg{false, "图片数据不正确" + err.Error(), 1})
		return
	}

	// 按"年/月/日"创建文件夹, 防止一个文件夹内文件过多造成读取缓慢
	filePath := "student/" + common.GetNowWithFormat("2006") + "/"
	filePath += common.GetNowWithFormat("01") + "/"
	filePath += common.GetNowWithFormat("02") + "/"

	rand.Seed(time.Now().UnixNano())
	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
	captcha := fmt.Sprintf("%6v", rnd.Int31n(1000000))

	fileName := captcha + "_" + common.ToStr(fieldName)
	fileUrl := filePath + fileName + "." + common.ToStr(imgType)

	// 绝对路径(防止"MkdirAll"将文件夹创建在"C:\Windows\System32")
	absPath := common.Config.UploadPath
	err = common.CreateChildDir(absPath + filePath)
	if err != nil {
		logger.Error("创建文件夹发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "创建文件夹发生错误" + err.Error(), 1})
		return
	}

	file, err := os.Create(absPath + fileUrl)
	if err != nil {
		logger.Error("创建图片文件发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "创建图片文件发生错误" + err.Error(), 1})
		return
	}
	_, err = io.WriteString(file, string(imgStr))
	_ = file.Close()
	if err != nil {
		logger.Error("保存图片文件发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "保存图片文件发生错误" + err.Error(), 1})
		return
	}

	// 缩略图上传
	imgStr, err = base64.StdEncoding.DecodeString(b64sm.(string))
	if err != nil {
		logger.Error("缩略图格式不正确", err)
		web.ServeJSON(w, web.JsonMsg{false, "缩略图格式不正确" + err.Error(), 1})
		return
	}

	fileUrl = filePath + fileName + "_sm." + common.ToStr(imgType)
	file, err = os.Create(absPath + fileUrl)
	if err != nil {
		logger.Error("创建缩略图文件发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "创建缩略图文件发生错误" + err.Error(), 1})
		return
	}
	_, err = io.WriteString(file, string(imgStr))
	_ = file.Close()
	if err != nil {
		logger.Error("保存缩略图文件发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "保存缩略图文件发生错误" + err.Error(), 1})
		return
	}

	result := map[string]interface{}{}
	result["status"] = 0
	result["success"] = true
	result["msg"] = "图片上传成功"
	result["imageUrl"] = fileUrl
	web.ServeJSON(w, result)
}
